import sim.engine.*;
import sim.util.Bag;
import sim.util.Int2D;

public class Civilian extends Agent implements Steppable{
	private static final long serialVersionUID = 1L;
	
	private double govtLegitimacy = 0;
	private double grievance = 0;	
	private double riskAversion = 0;
	private double perceivedHardship = 0;
	private double arrestProbability = 0;
	
	public Civilian(Int2D loc, double riskAversion, double perceivedHardship, double govtLegitimacy) {
		super(loc);
		this.riskAversion = riskAversion;
		this.perceivedHardship = perceivedHardship;
		this.govtLegitimacy = govtLegitimacy;
	}
	
	public void step(SimState state){
		EpsteinGrid epState = (EpsteinGrid)state;	
		epState.grid.getNeighborsMaxDistance(loc.x, loc.y, epState.civilianVision, false, neighborsX, neighborsY);
		
		if(jailTerm == 0){
			move(epState);
			setActive(epState);
		}
	}
	
	private void setActive(EpsteinGrid epState) {		
		boolean alreadyActive = false;
		
		if(this.active)
			alreadyActive = true;
		
		int activeV = 0;
		int copsV = 0;
		
		//Loop through all the agents within vision and count the number of active civilians and cops
		for(int i = 0; i < neighborsX.size(); i++){
			int x = neighborsX.get(i);
			int y = neighborsY.get(i);
			Bag agents = epState.grid.getObjectsAtLocation(x, y);
			
			if(agents != null){
				Agent agent;
				for(int j = 0; j < agents.size(); j++){
					agent = (Agent)agents.get(j);
					
					if(agent instanceof Civilian && agent.active){
						activeV++;
					}
					else if(agent instanceof Cop){
						copsV++;
					}
				}
			}		
		}
		
		/*Calculations for going active*/
		arrestProbability = 1 - Math.exp(-2.3*((copsV/(activeV+1))));
		grievance = perceivedHardship * (1 - govtLegitimacy);
		this.active = (grievance - (riskAversion * arrestProbability)) > epState.threshold;
		
		if(!alreadyActive && this.active){
			epState.activeCount++;
			epState.quietCount--;
		}
		else if(alreadyActive && !this.active){
			epState.activeCount--;
			epState.quietCount++;
		}
	}
	
	public double getGrievance(){return perceivedHardship * (1 - govtLegitimacy);}
	public double getRiskAversion(){return riskAversion;}
	public double getPerceivedHardship(){return perceivedHardship;}	
	public double getGovtLegitimacy(){return govtLegitimacy;}
}
